package com.easymin.weixin.manager.impl;


import com.alibaba.fastjson.JSON;
import com.google.common.base.Preconditions;
import com.alibaba.fastjson.JSONObject;
import com.easymin.weixin.common.DataGrid;
import com.easymin.weixin.common.PhoneNumberHelper;
import com.easymin.weixin.common.api.DaijiaApi;
import com.easymin.weixin.common.api.ErrandApi;
import com.easymin.weixin.common.api.FreightApi;
import com.easymin.weixin.common.api.PassengerApi;
import com.easymin.weixin.common.api.SalesApi;
import com.easymin.weixin.common.api.ZhuanApi;
import com.easymin.weixin.controller.v4.ResultTransport;
import com.easymin.weixin.entity.WxApplication;
import com.easymin.weixin.entity.passenger.Passenger;
import com.easymin.weixin.entity.sales.Coupon;
import com.easymin.weixin.entity.zhuanche.Order;
import com.easymin.weixin.manager.WxApplicationManager;
import com.easymin.weixin.manager.ZhuancheManager;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class DefaultZhuanCheManager implements ZhuancheManager {
  
  private static final Logger logger = LoggerFactory.getLogger(DefaultZhuanCheManager.class);

  @Autowired
  private ZhuanApi zhuanApi;
  @Autowired
  private DaijiaApi daijiaApi;
  @Autowired
  private PassengerApi passengerApi;
  @Autowired
  private WxApplicationManager wxApplicationManager;
  @Autowired
  private ErrandApi errandApi;
  @Autowired
  private FreightApi freightApi;
  @Autowired
  private SalesApi salesApi;

  @Override
  public Map<String, Object> createOrder(Long passengerId, String passengerName,
      String passengerPhone, String showPhone, Long companyId, String companyName, Long carTypeId,
      String channelName, String startAddress, String startAddressDetail, Double startLat,
      Double startLng, String endAddress, String endAddressDetail, Double endLat, Double endLng,
      Long serverTime, Long couponId, Double budgetPay, Double prestartPrice,
      Double premileagePrice, Double prerunTimePrice, Integer pretravelTime, Double premileage,
      Boolean prePay, String appKey, String addressUrl) throws Exception {
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("code", -1);
    map.put("msg", "创建专车订单失败");
    Preconditions.checkArgument(StringUtils.isNotBlank(appKey), "appKey不能为空");
    Preconditions.checkArgument(StringUtils.isNotBlank(passengerPhone), "客户电话号码不能为空");
    passengerPhone = passengerPhone.replaceAll(" ", "");
    passengerPhone = passengerPhone.replaceAll("-", "");
    if (!PhoneNumberHelper.isPhoneNumber(passengerPhone)) {
      map.put("code", -3);
      map.put("msg", "电话号码格式不正确");
      return map;
    }
    Passenger passenger = passengerApi.findById(passengerId, appKey);
    if (null == passenger) {
      map.put("code", -4);
      map.put("msg", "乘客不存在!");
      return map;
    }
    Long runningNumber = zhuanApi.countRunning(passengerId, appKey);
    if (runningNumber > 10) {
      map.put("code", -55);
      map.put("msg", "您今日下单已达到上限，继续下单请联系客服。");
      return map;
    }

    JSONObject object = daijiaApi.getServices(addressUrl);
    if (object != null) {
      Long num = 0L;
      boolean daijia = object.getBooleanValue("daijia");
      if (daijia) {
        num += daijiaApi.countNotPayAmounts(addressUrl, passengerId);
      }
      boolean zhuanche = object.getBooleanValue("zhuanche");
      if (zhuanche) {
        num += zhuanApi.countNotPayAmounts(passengerId, appKey);
      }
      boolean paotui = object.getBooleanValue("paotui");
      if (paotui) {
        num += errandApi.countNotPayAmounts(passengerId, appKey);
      }
      boolean freight = object.getBooleanValue("freight");
      if (freight) {
        num += freightApi.countNotPayAmounts(passengerId, appKey);
      }
      if (num > 0) {
        map.put("code", -54);
        map.put("msg", "还有未完成支付的订单，不能下单");
        return map;
      }
    }
    if (passenger.getInBlackList()) {
      map.put("code", -6);
      map.put("msg", "下单失败!");
      return map;
    }
    if (prePay && StringUtils.isBlank(endAddress)) {
      map.put("code", -7);
      map.put("msg", "请填写目的地");
      return map;

    }

    if (prePay && (null == endLat || null == endLng)) {
      map.put("code", -8);
      map.put("msg", "请重新填写目的地");
      return map;
    }
    if (prePay && null == budgetPay) {
      map.put("code", -9);
      map.put("msg", "请重新预算价格");
      return map;
    }

    Double shouldPay = budgetPay;
    Coupon coupon = null;
    if (null != couponId) {
      // 查询优惠券
      Map<String, Object> coupons = salesApi.coupons(couponId, appKey);
      int code = (int) coupons.get("code");
      if (code == 0) {
        coupon = (Coupon) coupons.get("data");
        if (null != coupon) {
          if (coupon.getCouponRule().getType() == 1) { // 1抵扣
            shouldPay = new BigDecimal(budgetPay)
            .subtract(coupon.getCouponRule().getMoney()).doubleValue();
            if (shouldPay < 0) {
              shouldPay = 0d;
            }
          } else { // 0打折
            BigDecimal couponMoney =
                (new BigDecimal(budgetPay).multiply(new BigDecimal(1 - (coupon.getCouponRule()
                    .getDiscount() / 10)))).setScale(0, BigDecimal.ROUND_DOWN);
            shouldPay = new BigDecimal(budgetPay).subtract(couponMoney).doubleValue();
          }
        }
      } else {
        map.put("code", -11);
        map.put("msg", (String) coupons.get("message"));
        return map;
      }
    }

    if (StringUtils.isBlank(passenger.getName())) {
      passenger.setName("先生/女士");
    }
    Order order = new Order();
    if (serverTime != null && serverTime != 0) {
      Date dtime = new Date(serverTime + 60 * 1000);
      Date date = new Date();
      if (date.after(dtime)) {
        map.put("code", -2);
        map.put("msg", "预约时间过时,请重新填写");
        return map;
      }
      order.setServerTime(dtime);
    } else {
      order.setServerTime(new Date());
    }
    order.setPassengerId(passenger.getId());
    order.setPassengerName(passenger.getName());
    order.setPassengerPhone(passenger.getPhone());
    order.setShowPhone(showPhone);
    order.setCompanyId(companyId);
    order.setCompanyName(companyName);
    order.setCarTypeId(carTypeId);
    order.setChannelName(channelName);
    order.setStartAddress(startAddress);
    order.setStartLat(startLat);
    order.setStartLng(startLng);
    order.setEndAddress(endAddress);
    order.setEndLat(endLat);
    order.setEndLng(endLng);
    order.setBudgetPay(budgetPay);
    order.setPrestartPrice(prestartPrice);
    order.setPremileagePrice(premileagePrice);
    order.setPrerunTimePrice(prerunTimePrice);
    order.setPremileage(premileage);
    order.setPretravelTime(pretravelTime);
    order.setStartAddressDetail(startAddressDetail);
    order.setEndAddressDetail(endAddressDetail);

    order.setCouponId(couponId);
    order.setShouldPay(shouldPay);

    JSONObject jsonObject = zhuanApi.create(order, passenger, prePay, appKey);

    if (null != jsonObject && jsonObject.getIntValue("code") == 0) {
      map.put("code", 0);
      map.put("msg", "下单成功");
      JSONObject jo = jsonObject.getJSONObject("data");
      Long orderId = jo.getLong("id");
      prePay = jo.getBoolean("prePay");
      budgetPay = jo.getDouble("budgetPay");
      Map<String, Object> data = new HashMap<String, Object>();
      data.put("orderId", orderId);
      data.put("prePay", prePay);
      data.put("overdraw", passenger.getAllowOverdraw());
      data.put("budgetPay", budgetPay);
      if (prePay) {
        Map<String, Object> map2 = daijiaApi.queryPaySetting(addressUrl);
        Boolean weixinPay = (Boolean) map2.get("weixinPay");
        Boolean aliPay = (Boolean) map2.get("aliPay");
        try {
          Boolean unionPay = (Boolean) map2.get("unionPay");
          data.put("unionPay", unionPay);
        } catch (Exception e) {
          data.put("unionPay", false);
        }
        data.put("weixinPay", weixinPay);
        data.put("aliPay", aliPay);
        data.put("overdraw", passenger.getAllowOverdraw());
      } else {
        daijiaApi.pushCreate(addressUrl, orderId);
        if (couponId != null) {
          salesApi.update(couponId, 2, appKey);
        }
      }
      map.put("data", data);
    }
    return map;
  }

  // 评价订单
  @Override
  public String review(Long orderId, Double score, String content, String appKey) {
    String result = null;
 
    // 看订单是否已经评价
    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    JSONObject json = daijiaApi.findZhuancheOrder(wxApplication.getAddress(), orderId);
    if (null != json && json.getJSONObject("data").getBooleanValue("review")) {
    	return "订单已评价，请勿重复评价";
    }
    
    JSONObject jsonObject = zhuanApi.review(orderId, score, content, appKey);
    int code = jsonObject.getIntValue("code");
    if (code != 0) {
      result = "评价失败";
    }
    return result;
  }

  @Override
  public DataGrid<Map<String, Object>> findByParam(Long passengerId, Integer page, Integer rows,
      String status, String appKey) {
    if (StringUtils.isBlank(status)) {
      status = "uncancel";
    }
    return zhuanApi.findByParam(passengerId, page, rows, status, appKey);
  }

  @Override
  public Map<String, Object> update(String address, Long orderId, Long employId, String employName,
      String employPhone, Long employCompanyId, String employNo, String employPhoto,
      Double employScore, String action, String operator, String cause, String appKey) {
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("code", -1);
    map.put("msg", "操作失败");
    map.put("data", null);
    if ("cancel".equals(action)) {
      try {
        Order order = zhuanApi.findById(orderId, appKey);
        Long cancelEmployId = order.getEmployId();
        zhuanApi.updateToCancel(orderId, cause, operator, appKey);
        map.put("code", 0);
        map.put("msg", "退款成功,销单成功");
        map.put("data", null);
        try {
          daijiaApi.pushCancel(address, orderId, cancelEmployId);// 专车订单销单推送
        } catch (Exception ex) {
          System.err.println("专车订单销单推送错误:" + ex.getMessage());
          logger.error(ex.getMessage());
        }
      } catch (Exception ex) {
        logger.error(ex.getMessage());
        map.put("code", -1);
        map.put("msg", "销单失败");
        map.put("data", null);
      }
    } else if ("wait".equals(action)) {
      try {
        zhuanApi.updateToWait(orderId, operator, appKey);
        map.put("code", 0);
        map.put("msg", "到达预约地");
        map.put("data", null);
        try {
          daijiaApi.pushWaitZhuan(address, orderId);// 到达预约地发短信
        } catch (Exception ex) {
          System.err.println("到达预约地发短信错误:" + ex.getMessage());
          logger.error(ex.getMessage());
        }
      } catch (Exception ex) {
        logger.error(ex.getMessage());
        map.put("code", -1);
        map.put("msg", "到达预约地失败");
        map.put("data", null);
      }
    } else if ("run".equals(action)) {
      try {
        Order order = zhuanApi.findById(orderId, appKey);
        if (order.getStatus() == 6) {
          map.put("code", -6);
          map.put("msg", "订单已销单");
          map.put("data", null);
        } else if (order.getStatus() == 0) {
          map.put("code", -5);
          map.put("msg", "订单已收回");
          map.put("data", null);
        } else {
          zhuanApi.updateToRun(orderId, operator, appKey);
          try {
            daijiaApi.pushRunOrderZhuan(address, orderId);
          } catch (Exception ex) {
            System.err.println("专车出发推送错误" + ex.getMessage());
            logger.error(ex.getMessage());
          }

          map.put("code", 0);
          map.put("msg", "开始执行");
          map.put("data", null);
        }
      } catch (Exception ex) {
        map.put("code", -1);
        map.put("msg", "执行失败");
        map.put("data", null);
      }
    } else if ("jiedan".equals(action)) {
      try {
        Map<String, Object> map2 = daijiaApi.queryDriver(address, employId);
        Boolean success = (Boolean) map2.get("success");
        if (success) {
          zhuanApi.updateToJiedan(orderId, employId, employName, employPhone, employCompanyId,
              employNo, employPhoto, employScore, operator, appKey);
          map.put("code", 0);
          map.put("msg", "接单成功");
          map.put("data", orderId);
          try {
            daijiaApi.updateBusyDriver(address, employId);
            daijiaApi.pushJiedan(address, orderId); // 专车订单接单推送
          } catch (Exception ex) {
            System.err.println("专车订单接单推送" + ex.getMessage());
            logger.error(ex.getMessage());
          }
        } else {
          map.put("code", -1);
          map.put("msg", map2.get("message"));
        }
      } catch (Exception ex) {
        logger.error(ex.getMessage());
        map.put("code", -1);
        map.put("msg", "接单失败");
        map.put("data", null);
      }
    } else if ("refuse".equals(action)) {
      try {
        zhuanApi.updateToRefuse(orderId, employId, cause, operator, appKey);
        try {
          daijiaApi.updateDriver(address, orderId);
          daijiaApi.refuseOrder(address, orderId, employId, cause);
        } catch (Exception ex) {
          System.err.println("拒单推送错误" + ex.getMessage());
          logger.error(ex.getMessage());
        }
        map.put("code", 0);
        map.put("msg", "拒接成功");
        map.put("data", null);
      } catch (Exception ex) {
        map.put("code", -1);
        map.put("msg", "拒接失败");
        map.put("data", null);
      }
    }
    return map;
  }

  @Override
  public String hasten(Long orderId, String appKey) {
    String hasten = zhuanApi.hasten(orderId, appKey);
    return hasten;
  }

  @Override
  public Map<String, Object> findOrder(String address, Long orderId, String appKey)
      throws Exception {
    Map<String, Object> map = new HashMap<String, Object>();

    Order order = zhuanApi.findById(orderId, appKey);

    map.put("id", order.getId());
    map.put("orderNo", order.getOrderNo());
    map.put("passengerId", order.getPassengerId());
    map.put("passengerPhone", order.getPassengerPhone());
    map.put("showPhone", order.getShowPhone());
    map.put("passengerName", order.getPassengerName());
    map.put("startAddress", order.getStartAddress());
    map.put("startAddressDetail", order.getStartAddressDetail());
    map.put("startLat", order.getStartLat());
    map.put("startLng", order.getStartLng());
    map.put("endAddress", order.getEndAddress());
    map.put("endAddressDetail", order.getEndAddressDetail());
    map.put("endLat", order.getEndLat());
    map.put("endLng", order.getEndLng());
    map.put("status", order.getStatus());
    map.put("serverTime", order.getServerTime().getTime());
    map.put("review", order.getReview());
    map.put("treatment", order.getTreatment());
    map.put("budgetPay", order.getBudgetPay());
    map.put("startPrice", order.getStartPrice());
    map.put("mileagePrice", order.getMileagePrice());
    map.put("runTimePrice", order.getRunTimePrice());
    map.put("mileage", order.getMileage());
    map.put("runTime", order.getRunTime());
    map.put("realPay", order.getRealPay());
    map.put("carTypeId", order.getCarTypeId());
    map.put("carTypeName", order.getCarTypeName());
    map.put("channelName", order.getChannelName());
    map.put("companyName", order.getCompanyName());
    map.put("companyId", order.getCompanyId());
    map.put("orderMemos", order.getOrderMemos());
    map.put("employId", order.getEmployId());
    map.put("employName", order.getEmployName());
    map.put("employNo", order.getEmployNo());
    map.put("areaId", order.getAreaId());
    map.put("carNumber", order.getCarNumber());
    map.put("carName", order.getCarName());
    return map;
  }

  @Override
  public Order findOne(Long orderId, String appKey) throws Exception {
    Order order = zhuanApi.findById(orderId, appKey);
    return order;
  }

  @Override
  public ResultTransport findOneV4(Long orderId, String address, String appKey) {
    return zhuanApi.findOneV4(orderId, address, appKey);
  }
  
  @Override
  public ResultTransport yuyueDriverDo(Long orderId, Long employId, String appKey, String serverUrl) {

    return zhuanApi.yuyueDriverDo(orderId, employId, appKey, serverUrl);
  }

  @Override
  public ResultTransport jiedan(Long orderId, Long employId, String appKey, String serverUrl) {

    return zhuanApi.updateToJiedanV4(orderId, employId, appKey, serverUrl);
  }

  @Override
  public ResultTransport refuse(Long orderId, Long employId, String cause, String employName,
      String appKey) {

    return zhuanApi.refuseV4(orderId, employId, cause, employName, appKey);
  }

  @Override
  public ResultTransport queryTypeV4(Long companyId, String appKey) {
    return zhuanApi.queryTypeV4(companyId, appKey);
  }

  @Override
  public ResultTransport waitV4(Long orderId, String employName, String appKey, String serverUrl) {
    return zhuanApi.waitV4(orderId, employName, appKey, serverUrl);
  }

  @Override
  public ResultTransport runV4(Long orderId, String operator, String appKey,
      String realStartAddress,Double realStartLat,Double realStartLng) {
    return zhuanApi.runV4(orderId, operator, appKey,realStartAddress,realStartLat,realStartLng);
  }

  @Override
  public synchronized ResultTransport grabV4(Long orderId, Long employId, String employName,
      String employPhone, Long companyId, String employAccount, String employPhoto,
      Double employScore, String operator, Long rentCompanyId, String rentCompanyName, String appKey) {
    return zhuanApi.grabV4(orderId, employId, employName, employPhone, companyId, employAccount,
        employPhoto, employScore, operator, rentCompanyId, rentCompanyName, appKey);
  }

  @Override
  public ResultTransport createmoreV4(String passengerPhone, Long carTypeId, String startAddress,
      Double startLat, Double startLng, Long employId, String employName, String employPhone,
      Long companyId, String appKey) {
    return zhuanApi.createmoreV4(passengerPhone, carTypeId, startAddress, startLat, startLng,
        employId, employName, employPhone, companyId, appKey);
  }

  @Override
  public ResultTransport queryOneType(Long carTypeId, String appKey) {
    return zhuanApi.queryOneType(carTypeId, appKey);
  }

  @Override
  public ResultTransport updateToPlace(Long orderId, String toPlace, Double longitude,
      Double latitude, String appKey) {
    return zhuanApi.updateToPlaceV4(orderId, toPlace, longitude, latitude, appKey);
  }

@Override
public ResultTransport findByParamsInBook(Integer page, Integer rows,
		Double latitude, Double longitude, String serverUrl, Integer carTypeId,
		String appKey) {
	return zhuanApi.findByParamsInBook(page, rows, latitude, longitude, serverUrl, carTypeId, appKey);
}

@Override
public ResultTransport countByParamsInBook(Double latitude, Double longitude,
		String serverUrl, Integer carTypeId, String appKey) {
	return zhuanApi.countByParamsInBook(latitude, longitude, serverUrl, carTypeId, appKey);
}

}
